home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / domhdr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  6.1 KB  |  281 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "domain.h"
  4.  
  5. static int dn_expand __ARGS((char *msg,char *eom,char *compressed,char *full,
  6.     int fullen));
  7. static char *getq __ARGS((struct quest *qp,char *msg,char *cp));
  8. static char *ntohrr __ARGS((struct rr *rrp,char *msg,char *cp));
  9.  
  10. int
  11. ntohdomain(dhdr,bpp)
  12. register struct dhdr *dhdr;
  13. struct mbuf **bpp;
  14. {
  15.     int16 tmp,len;
  16.     register int16 i;
  17.     char *msg,*cp;
  18.  
  19.     len = len_p(*bpp);
  20.     msg = mallocw(len);
  21.     pullup(bpp,msg,len);
  22.     memset((char *)dhdr,0,sizeof(*dhdr));
  23.  
  24.         dhdr->id = get16(&msg[0]);
  25.     tmp = get16(&msg[2]);
  26.     if(tmp & 0x8000)
  27.         dhdr->qr = 1;
  28.     dhdr->opcode = (tmp >> 11) & 0xf;
  29.     if(tmp & 0x0400)
  30.         dhdr->aa = 1;
  31.     if(tmp & 0x0200)
  32.         dhdr->tc = 1;
  33.     if(tmp & 0x0100)
  34.         dhdr->rd = 1;
  35.     if(tmp & 0x0080)
  36.         dhdr->ra = 1;
  37.     dhdr->rcode = tmp & 0xf;
  38.     dhdr->qdcount = get16(&msg[4]);
  39.     dhdr->ancount = get16(&msg[6]);
  40.     dhdr->nscount = get16(&msg[8]);
  41.     dhdr->arcount = get16(&msg[10]);
  42.  
  43.     /* Now parse the variable length sections */
  44.     cp = &msg[12];
  45.  
  46.     /* Question section */
  47.     if(dhdr->qdcount != 0)
  48.         dhdr->qlist = (struct quest **)mallocw(dhdr->qdcount *
  49.          sizeof(struct quest *));
  50.     for(i=0;i<dhdr->qdcount;i++){
  51.         dhdr->qlist[i] = (struct quest *)mallocw(sizeof(struct quest));
  52.         if((cp = getq(dhdr->qlist[i],msg,cp)) == NULLCHAR){
  53.             free(msg);
  54.             return -1;
  55.         }
  56.     }
  57.     /* Answer section */
  58.     if(dhdr->ancount != 0)
  59.         dhdr->ans = (struct rr **)mallocw(dhdr->ancount *
  60.          sizeof(struct rr *));
  61.     for(i=0;i<dhdr->ancount;i++){
  62.         dhdr->ans[i] = (struct rr *)mallocw(sizeof(struct rr));
  63.         if((cp = ntohrr(dhdr->ans[i],msg,cp)) == NULLCHAR){
  64.             free(msg);
  65.             return -1;
  66.         }
  67.     }        
  68.     /* Name server (authority) section */
  69.     if(dhdr->nscount != 0)
  70.         dhdr->ns = (struct rr **)mallocw(dhdr->nscount *
  71.          sizeof(struct rr *));
  72.     for(i=0;i<dhdr->nscount;i++){
  73.         dhdr->ns[i] = (struct rr *)mallocw(sizeof(struct rr));
  74.         if((cp = ntohrr(dhdr->ns[i],msg,cp)) == NULLCHAR){
  75.             free(msg);
  76.             return -1;
  77.         }
  78.     }
  79.     /* Additional section */
  80.     if(dhdr->arcount != 0)
  81.         dhdr->add = (struct rr **)mallocw(dhdr->arcount *
  82.          sizeof(struct rr *));
  83.     for(i=0;i<dhdr->arcount;i++){
  84.         dhdr->add[i] = (struct rr *)mallocw(sizeof(struct rr));
  85.         if((cp = ntohrr(dhdr->add[i],msg,cp)) == NULLCHAR){
  86.             free(msg);
  87.             return -1;
  88.         }
  89.     }
  90.     free(msg);
  91.     return 0;
  92. }
  93. static char *
  94. getq(qp,msg,cp)
  95. struct quest *qp;
  96. char *msg;
  97. char *cp;
  98. {
  99.     int len;
  100.     char *name;
  101.  
  102.     name = mallocw(512);
  103.     len = dn_expand(msg,NULLCHAR,cp,name,512);
  104.     if(len == -1){
  105.         free(name);
  106.         return NULLCHAR;
  107.     }
  108.     cp += len;
  109.     qp->qname = strdup(name);
  110.     qp->qtype = get16(cp);
  111.     cp += 2;
  112.     qp->qclass = get16(cp);
  113.     cp += 2;
  114.     free(name);
  115.     return cp;
  116. }
  117. /* Read a resource record from a domain message into a host structure */
  118. static char *
  119. ntohrr(rrp,msg,cp)
  120. struct rr *rrp;    /* Pointer to allocated resource record structure */
  121. char *msg;    /* Pointer to beginning of domain message */
  122. char *cp;    /* Pointer to start of encoded RR record */
  123. {
  124.     int len;
  125.     char *name;
  126.  
  127.     name = mallocw(512);
  128.     if((len = dn_expand(msg,NULLCHAR,cp,name,512)) == -1){
  129.         free(name);
  130.         return NULLCHAR;
  131.     }
  132.     cp += len;
  133.     rrp->name = strdup(name);
  134.     rrp->type = get16(cp);
  135.     cp += 2;
  136.     rrp->class = get16(cp);
  137.     cp+= 2;
  138.     rrp->ttl = get32(cp);
  139.     cp += 4;
  140.     rrp->rdlength = get16(cp);
  141.     cp += 2;
  142.     switch(rrp->type){
  143.     case TYPE_CNAME:
  144.     case TYPE_MB:
  145.     case TYPE_MG:
  146.     case TYPE_MR:
  147.     case TYPE_NS:
  148.     case TYPE_PTR:
  149.         /* These types all consist of a single domain name;
  150.          * convert it to ascii format
  151.          */
  152.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  153.         if(len == -1){
  154.             free(name);
  155.             return NULLCHAR;
  156.         }
  157.         rrp->rdata.name = strdup(name);
  158.         rrp->rdlength = strlen(name);
  159.         cp += len;
  160.         break;
  161.     case TYPE_A:
  162.         /* Just read the address directly into the structure */
  163.         rrp->rdata.addr = get32(cp);
  164.         cp += 4;
  165.         break;
  166.     case TYPE_HINFO:
  167.         rrp->rdata.hinfo.cpu = strdup(cp);
  168.         cp += strlen(cp) + 1;
  169.  
  170.         rrp->rdata.hinfo.os = strdup(cp);
  171.         cp += strlen(cp) + 1;
  172.         break;
  173.     case TYPE_MX:
  174.         rrp->rdata.mx.pref = get16(cp);
  175.         cp += 2;
  176.         /* Get domain name of exchanger */
  177.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  178.         if(len == -1){
  179.             free(name);
  180.             return NULLCHAR;
  181.         }
  182.         rrp->rdata.mx.exch = strdup(name);
  183.         cp += len;
  184.         break;
  185.     case TYPE_SOA:
  186.         /* Get domain name of name server */
  187.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  188.         if(len == -1){
  189.             free(name);
  190.             return NULLCHAR;
  191.         }
  192.         rrp->rdata.soa.mname = strdup(name);
  193.         cp += len;
  194.  
  195.         /* Get domain name of responsible person */
  196.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  197.         if(len == -1){
  198.             free(name);
  199.             return NULLCHAR;
  200.         }
  201.         rrp->rdata.soa.rname = strdup(name);
  202.         cp += len;
  203.  
  204.         rrp->rdata.soa.serial = get32(cp);
  205.         cp += 4;
  206.         rrp->rdata.soa.refresh = get32(cp);
  207.         cp += 4;
  208.         rrp->rdata.soa.retry = get32(cp);
  209.         cp += 4;
  210.         rrp->rdata.soa.expire = get32(cp);
  211.         cp += 4;
  212.         rrp->rdata.soa.minimum = get32(cp);
  213.         cp += 4;
  214.         break;
  215.     case TYPE_TXT:
  216.         /* Just stash */
  217.         rrp->rdata.data = mallocw(rrp->rdlength);
  218.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  219.         cp += rrp->rdlength;
  220.         break;
  221.     default:
  222.         /* Ignore */
  223.         cp += rrp->rdlength;
  224.         break;
  225.     }
  226.     rrp->dupe = 0;
  227.     free(name);
  228.     return cp;
  229. }
  230.  
  231. /* Convert a compressed domain name to the human-readable form */
  232. static int
  233. dn_expand(msg,eom,compressed,full,fullen)
  234. char *msg;        /* Complete domain message */
  235. char *eom;
  236. char *compressed;    /* Pointer to compressed name */
  237. char *full;        /* Pointer to result buffer */
  238. int fullen;        /* Length of same */
  239. {
  240.     unsigned int slen;    /* Length of current segment */
  241.     register char *cp;
  242.     int clen = 0;    /* Total length of compressed name */
  243.     int indirect = 0;    /* Set if indirection encountered */
  244.     int nseg = 0;        /* Total number of segments in name */
  245.  
  246.     cp = compressed;
  247.     for(;;){
  248.         slen = uchar(*cp++);    /* Length of this segment */
  249.         if(!indirect)
  250.             clen++;
  251.         if((slen & 0xc0) == 0xc0){
  252.             if(!indirect)
  253.                 clen++;
  254.             indirect = 1;
  255.             /* Follow indirection */
  256.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  257.             slen = uchar(*cp++);
  258.         }
  259.         if(slen == 0)    /* zero length == all done */
  260.             break;
  261.         fullen -= slen + 1;
  262.         if(fullen < 0)
  263.             return -1;
  264.         if(!indirect)
  265.             clen += slen;
  266.         while(slen-- != 0)
  267.             *full++ = *cp++;
  268.         *full++ = '.';
  269.         nseg++;
  270.     }
  271.     if(nseg == 0){
  272.         /* Root name; represent as single dot */
  273.         *full++ = '.';
  274.         fullen--;
  275.     }
  276.     *full++ = '\0';
  277.     fullen--;
  278.     return clen;    /* Length of compressed message */
  279. }
  280.  
  281.